﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using yq.IBase;
using yq.Basis;
using yq.Dictionary;

namespace yq.ControllerBase
{
    /// <summary>
    /// 验证拦截
    /// 本拦截没有错误提示，所以只用在数据一致性验证
    /// </summary>
    public class VerifyFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 使用过的model缓存
        /// </summary>
        public const string KeyString = "___VerifyFilter___";

        /// <summary>
        /// 取数据Request[XXX]值
        /// </summary>
        public const string RequestDataId = "___VerifyFilter_RequestDataId___";

        public string requestDataId { get; set; }

        public IList<Verify> vfy = new List<Verify>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_requestDataId">Request中对象的主键名称</param>
        /// <param name="_verifyName">验证委托名 VerifyHelp 中的名称 如VerifyHelp.UserAccount</param>
        public VerifyFilterAttribute(string _requestDataId,params string[] _verifyName)
        {
            requestDataId = _requestDataId;

            foreach (var key in _verifyName)
            {
                if (VerifyCaChe.Cache.ContainsKey(key))
                {
                    vfy.Add(VerifyCaChe.Cache[key]);
                }
            }
        }

        /// <summary>
        /// 执行前
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            System.Web.Mvc.ControllerBase controller = filterContext.Controller;

            //保存到缓存里
            controller.ViewData[RequestDataId] = requestDataId;

            if (filterContext.HttpContext.Request[requestDataId] != null)
            {
                foreach (var verify in vfy)
                {
                    ReturnValue<object> rv = verify.Run(filterContext.HttpContext.Request[requestDataId]);

                    if (rv.Status== ReturnEnum.Yes)
                    {
                        //保存到缓存里
                        filterContext.Controller.ViewData[KeyString] = rv.Value;
                    }
                    else
                    {
                        filterContext.Result = ErrorFilterAttribute.GetError(ErrorFilterType.Default, "未通过对象验证（VerifyFilter is null）", filterContext.Controller);
                        return;
                    }
                }
            }
            else
            {
                filterContext.Result = ErrorFilterAttribute.GetError(ErrorFilterType.Default, "请求数据缺失（Request is null）", filterContext.Controller);
            }
        }
    }

    /// <summary>
    /// 验证辅组类
    /// </summary>
    public class Verify
    {
        public Verify(Func<string, ReturnValue<object>> _fun)
        {
            funObj = _fun;
        }

        /// <summary>
        /// 验证方法的封装
        /// </summary>
        private Func<string, ReturnValue<object>> funObj = null;

        /// <summary>
        /// 验证运算
        /// </summary>
        /// <param name="id">该数据的主键Id</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public ReturnValue<object> Run(string id)
        {
            return funObj(id);
        }
    }
    
    
    /// <summary>
    /// 验证缓存，保存验证缓存的字典
    /// yq.Controller.VerifyHelp 来添加和初始化验证类到这个字典
    /// </summary>
    public class VerifyCaChe
    {
        /// <summary>
        /// 验证缓存
        /// </summary>
        private static Dictionary<string, Verify> _Cache = new Dictionary<string, Verify>();

        public static Dictionary<string, Verify> Cache
        {
            get { return VerifyCaChe._Cache; }
        }


        /// <summary> 
        /// 获取验证类 
        /// </summary>
        /// <typeparam name="T">要验证的类型</typeparam>
        /// <param name="_fun">验证执行方法</param>
        /// <returns></returns>
        public static void Add<T>(string verifyKey, Func<T, CurrentUser, bool> _fun) where T : ModelBase<T>, new()
        {
            //封装为待验证类
            Func<string, ReturnValue<object>> funObj = (key) =>
            {
                ReturnValue<object> rv = new ReturnValue<object>();

                //取数据
                T model = yq.Basis.ModelBase<T>.Load(key);

                //执行验证方法
                if (model.IsLoad == true && _fun(model, yq.ControllerBase.BaseController.GetCurrentUser))
                {
                    rv.True(model);
                }
                else
                {
                    rv.False("验证失败");
                }

                return rv;
            };

            _Cache.Add(verifyKey, new Verify(funObj));
        }
    }

}